//
//  UIView+AG.swift
//  ASW
//
//  Created by zhuxuhong on 2020/11/24.
//

import UIKit
import BWToolKit

extension UIView {
    public static var viewFromXib: Self? {
        return Bundle.main.loadNibNamed("\(Self.self)", owner: nil, options: nil)?.first as? Self
    }
}

extension UIView {
    public enum ZCornerPosition: String {
        case topLeft = "0"
        case topRight = "1"
        case bottomLeft = "2"
        case bottomRight = "3"
        case all = "4"
    }
    
    public func bw_createRoundedRectPath(
        with cornersAndRadius: [ZCornerPosition: CGFloat] = [.all: 10],
        for rect: CGRect
    ) -> CGPath {
        var topLeftRadius = cornersAndRadius[.topLeft] ?? 0
        var topRightRadius = cornersAndRadius[.topRight] ?? 0
        var bottomLeftRadius = cornersAndRadius[.bottomLeft] ?? 0
        var bottomRightRadius = cornersAndRadius[.bottomRight] ?? 0
        if let v = cornersAndRadius[.all] {
            topLeftRadius = v
            topRightRadius = v
            bottomLeftRadius = v
            bottomRightRadius = v
        }
        
        let path = CGMutablePath()
        
        let midTopPoint = CGPoint(x: rect.midX, y: rect.minY)
        path.move(to: midTopPoint)
        
        let topRightPoint = CGPoint(x: rect.maxX, y: rect.minY)
        let bottomRightPoint = CGPoint(x: rect.maxX, y: rect.maxY)
        let bottomLeftPoint = CGPoint(x: rect.minX, y: rect.maxY)
        let topLeftPoint = CGPoint(x: rect.minX, y: rect.minY)
        
        path.addArc(tangent1End: topRightPoint,
              tangent2End: bottomRightPoint,
              radius: topRightRadius)

        path.addArc(tangent1End: bottomRightPoint,
          tangent2End: bottomLeftPoint,
          radius: bottomRightRadius)

        path.addArc(tangent1End: bottomLeftPoint,
          tangent2End: topLeftPoint,
          radius: bottomLeftRadius)

        path.addArc(tangent1End: topLeftPoint,
          tangent2End: topRightPoint,
          radius: topLeftRadius)

        path.closeSubpath()
        
        return path
    }
}

extension UIView {
    public typealias GestureHandler = (UIGestureRecognizer)->Void
    
    struct GestureAssociatedKeys {
        static var tapped = "tapped"
        static var longPressed = "longPressed"
    }
    
    public func bw_gestureTapped(_ handler: @escaping GestureHandler) {
        bw_gestureTapped(self, #selector(_gestureTapped(_:)))
        Objcer.setASValue(handler, for: self, key: &GestureAssociatedKeys.tapped, policy: .copy)
    }
    public func bw_gestureLongPressed(_ handler: @escaping GestureHandler) {
        bw_gestureLongPressed(self, #selector(_gestureLongPressed(_:)))
        Objcer.setASValue(handler, for: self, key: &GestureAssociatedKeys.longPressed, policy: .copy)
    }
    public func bw_gestureTapped(_ target: Any, _ selector: Selector?, taps: Int = 1) {
        isUserInteractionEnabled = true
        let gesture = UITapGestureRecognizer(target: target, action: selector)
        gesture.numberOfTapsRequired = taps
        addGestureRecognizer(gesture)
    }
    public func bw_gestureLongPressed(_ target: Any, _ selector: Selector?) {
        isUserInteractionEnabled = true
        addGestureRecognizer(UILongPressGestureRecognizer(target: target, action: selector))
    }
    
    @objc private func _gestureTapped(_ sender: UITapGestureRecognizer) {
        if let handler = Objcer.getASValue(for: self, key: &GestureAssociatedKeys.tapped) as? GestureHandler {
            handler(sender)
        }
    }
    @objc private func _gestureLongPressed(_ sender: UILongPressGestureRecognizer) {
        if let handler = Objcer.getASValue(for: self, key: &GestureAssociatedKeys.longPressed) as? GestureHandler {
            handler(sender)
        }
    }
}

extension UIView {
    public func bw_renderToImage(opaque: Bool = false) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, opaque, 0)
        defer {
            UIGraphicsEndImageContext()
        }
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        layer.render(in: context)
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

extension UIView.AutoresizingMask {
    public static var bw_flexibleSize: Self {
        return [.flexibleWidth, .flexibleHeight]
    }
}
